package fr.generali.accueilclient.gwt.client.ui.components.form.formitem;

import java.util.List;

import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;

import fr.generali.accueilclient.gwt.client.ui.components.form.ListBox;

/**
 * Champ de saisie de type {@link FormItem}, intégrant une {@link ListBox}.
 */
public class ListFormItem<T> extends LabelFormItem<T> implements HasChangeHandlers, LeafValueEditor<T> {

    /** La {@link TextBox} affichée lorsque l'élément est en mode édition. */
    private ListBox<T> valueListBox;

    @SuppressWarnings("unchecked")
    public ListFormItem() {
        this(true);
    }

    public ListFormItem(boolean addNotSpecifiedTextItem) {
        super(new ListBox<T>());
        valueListBox = (ListBox<T> ) editableWidget;
        if (addNotSpecifiedTextItem) {
            valueListBox.addItemValue(NOT_SPECIFIED_TEXT, (T ) null);
        }

        initHandlers();
    }

    /**
     * Initialisation des handlers du champ de saisie.<br>
     * Permet d'activer les validations implémentées dans {@link FormItem}<br>
     */
    private void initHandlers() {
        this.valueListBox.addChangeHandler(new ChangeHandler() {
            @Override
            public void onChange(ChangeEvent event) {
                ListFormItem.this.onValueChanged();
            }
        });
    }

    /**
     * Permet de savoir quand le champ a le focus<br>
     */
    @Override
    public HandlerRegistration addChangeHandler(ChangeHandler handler) {
        return valueListBox.addChangeHandler(handler);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void doSetValue(T value, boolean valueIsNullOrEmpty) {
        valueListBox.setSelectedValue(value);
        if (!valueIsNullOrEmpty) {
            valueLabel.setText(valueListBox.getSelectedText());
        }
    };

    /**
     * Permet de savoir si le champ de saisie est vide ou pas en tenant<br>
     * compte du fait que le champ soit en édition ou non.<br>
     */
    @Override
    protected boolean isDataFilled() {
        return valueListBox.getSelectedIndex() >= 0 && valueListBox.getSelectedValue() != null;
    }

    /**
     * Permet de récupérer la valeur de la zone d'édition.<br>
     * Cette valeur est récupérée dans la {@link TextBox} ou dans le
     * {@link Label},<br>
     * en fonction de si le champ de saisie est en mode édition ou pas.<br>
     * 
     * @return la valeur de la zone d'édition
     */
    @Override
    public T getValue() {
        return valueListBox.getSelectedValue();
    }

    /**
     * Permet de récupérer la liste des valeurs sélectionnées dans la liste.<br>
     * Ces valeurs sont récupérées dans la {@link ListBox}<br>
     * en fonction de la sélection<br>
     * 
     * @return la valeur de la zone d'édition
     */
    public List<T> getValues() {
        return valueListBox.getSelectedValues();
    }

    /**
     * vide la liste
     */
    public void clear() {
        valueListBox.clear();
        valueListBox.addItemValue(NOT_SPECIFIED_TEXT, (T ) null);
    }
    
    /**
     * sélectionne / désélectionne un item de la liste
     * 
     * @param index l'index de l'item à  sélectionner ou pas
     * @param selected <code>true</code> pour sélectionner l'item
     */
    public void setItemSelected(int index, boolean selected) {
        valueListBox.setItemSelected(index, selected);
    }

    /**
     * Permet d'ajouter une valeur dans la {@link ListBox}.<br>
     * 
     * @param item
     * @param value
     */
    public void addItem(String item, T value) {
        valueListBox.addItemValue(item, value);
    }

    @Override
    protected boolean valueIsNullOrEmpty(T value) {
        return value == null;
    }

    public void setVisibleItemCount(int itemCount) {
        valueListBox.setVisibleItemCount(itemCount);
    }

    public void setMultipleSelect(boolean multipleSelect) {
        valueListBox.setMultipleSelect(multipleSelect);
    }

    public void setEnabled(boolean enabled) {
        valueListBox.setEnabled(enabled);
    }

}
